package com.googlecode.lookie.platform;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.richclient.application.Application;

/*
 * The main driver for a Spring Rich Client application.
 * 
 * <p> This class displays a configurable splash screen and launches a rich client {@link
 * Application}. Both the splash screen and the application to be launched are expected to be
 * defined as beans, under the names {@link #SPLASH_SCREEN_BEAN_ID} and {@link #APPLICATION_BEAN_ID}
 * respectively, in one of the application contexts provided to the constructor. </p>
 * 
 * <p> For quick loading and display of the splash screen while the rest of the application is being
 * initialized, constructors are provided that take a separate startup context. The startup context
 * will be searched for the {@link #SPLASH_SCREEN_BEAN_ID} bean, which will then be displayed before
 * the main application context is loaded and the application launched. If no startup context is
 * provided or it doesn't contain an appropriately named splash screen bean, an attempt will be made
 * to load a splash screen from the main application context. This can only happen after the main
 * application context has been loaded in its entirety so it is not the recommended approach for
 * displaying a splash screen. </p>
 * 
 * @author Keith Donald
 * 
 * @see Application
 */
public class PlatformLauncher
    implements InitializingBean
{

    /**
     * The name of the bean that defines the {@code Application} that this class
     * will launch.
     * {@value}
     */
    public static final String APPLICATION_BEAN_ID = "application";

    private final Log logger = LogFactory.getLog( getClass() );

    private Application application;

    public void setApplication( Application application )
    {
        this.application = application;
    }

    /**
     * Launches the rich client application. If no startup context has so far
     * been provided, the main application context will be searched for a splash
     * screen to display. The main application context will then be searched for
     * the {@link Application} to be launched, using the bean name
     * {@link #APPLICATION_BEAN_ID}. If the application is found, it will be
     * started.
     *
     */
    private void launchMyRichClient()
    {

        application.start();

        //        try {
        //            // To avoid deadlocks when events fire during initialization of some swing components
        //            // Possible to do: in theory not a single Swing component should be created (=modified) in the launcher thread...
        //            SwingUtilities.invokeAndWait(new Runnable() {
        //                public void run() {
        //                    application.start();
        //                }
        //            });
        //        }
        //        catch (InterruptedException e) {
        //            logger.warn("Application start interrupted", e);
        //        }
        //        catch (InvocationTargetException e) {
        //            logger.warn("Application start interrupted", e);
        //            Throwable cause = e.getCause();
        //            throw new IllegalStateException("Application start thrown an exception: " + cause.getMessage(), cause);
        //        }

        logger.info( "Launcher thread exiting..." );

    }

    public void afterPropertiesSet()
        throws Exception
    {
        logger.info( "starting" );
        launchMyRichClient();
    }

}
